#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
MCP联网搜索接口 - 集成Open-WebSearch MCP服务器
为云顶之弈助手提供联网搜索能力
"""

import os
import json
import asyncio
import subprocess
import sys
from typing import List, Dict, Optional, Any
from dataclasses import dataclass
import threading
import time

@dataclass
class SearchResult:
    """搜索结果数据类"""
    title: str
    url: str
    snippet: str
    engine: str
    timestamp: str = ""

class MCPWebSearchClient:
    """MCP联网搜索客户端"""

    def __init__(self, mcp_server_path: str = None):
        self.mcp_server_path = mcp_server_path or os.path.join(
            os.path.dirname(__file__),
            "open-webSearch-main",
            "build",
            "index.js"
        )
        self.server_process = None
        self.is_running = False
        self.search_id = 0
        self.session_id = None
        self.http_mode = False

    async def start_server(self):
        """启动MCP搜索服务器"""
        if self.is_running:
            return True

        try:
            print("🚀 启动MCP联网搜索服务器...")
            print(f"📁 服务器路径: {self.mcp_server_path}")

            # 检查服务器文件是否存在
            if not os.path.exists(self.mcp_server_path):
                print(f"❌ MCP服务器文件不存在: {self.mcp_server_path}")
                return False

            # 启动Node.js MCP服务器 (HTTP模式)
            env = os.environ.copy()
            env['MODE'] = 'http'  # 强制使用HTTP模式
            env['ENABLE_CORS'] = 'true'  # 启用CORS支持
            env['PORT'] = '3002'  # 使用不同端口避免冲突

            print("🔧 启动参数: MODE=http, ENABLE_CORS=true, PORT=3002")

            # 在Windows上使用shell=True来确保环境变量正确传递
            self.server_process = subprocess.Popen(
                ['node', self.mcp_server_path],
                env=env,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True,
                shell=os.name == 'nt'  # Windows需要shell=True
            )

            print("⏳ 等待MCP服务器启动...")
            # 等待服务器启动
            await asyncio.sleep(4)

            # 检查服务器进程状态
            if self.server_process.poll() is None:
                print("✅ MCP服务器进程启动成功")

                # 读取启动日志
                try:
                    # 读取stderr输出（Node.js日志通常在stderr）
                    stderr_output = ""
                    while self.server_process.poll() is None:
                        line = self.server_process.stderr.readline()
                        if not line:
                            break
                        stderr_output += line
                        if "HTTP server running on port" in line:
                            print("🌐 HTTP服务器已就绪")
                            break
                        elif "error" in line.lower() or "failed" in line.lower():
                            print(f"⚠️ 服务器警告: {line.strip()}")

                    if stderr_output:
                        print(f"📋 服务器启动日志:\n{stderr_output}")

                except Exception as e:
                    print(f"⚠️ 读取服务器日志失败: {e}")

                # 等待更长时间确保服务器完全启动
                await asyncio.sleep(2)

                # 尝试初始化MCP会话
                print("🔗 尝试初始化MCP会话...")
                try:
                    if await self.initialize_mcp_session():
                        self.is_running = True
                        self.http_mode = True
                        print("✅ MCP搜索服务器完全启动成功 (HTTP模式)")
                        print(f"🌐 服务器地址: http://localhost:3002")
                        return True
                    else:
                        print("⚠️ MCP会话初始化失败，但服务器已启动")
                        # 即使会话初始化失败，也标记为运行，后续可以重试
                        self.is_running = True
                        self.http_mode = True
                        print("🔄 服务器将在搜索时重试会话初始化")
                        return True
                except Exception as e:
                    print(f"⚠️ MCP会话初始化异常: {e}")
                    # 即使会话初始化失败，也标记为运行，后续可以重试
                    self.is_running = True
                    self.http_mode = True
                    print("🔄 服务器将在搜索时重试会话初始化")
                    return True
            else:
                # 服务器进程已退出
                stdout, stderr = self.server_process.communicate()
                print(f"❌ MCP服务器进程意外退出")
                if stderr:
                    print(f"错误信息: {stderr}")
                if stdout:
                    print(f"输出信息: {stdout}")
                return False

        except Exception as e:
            print(f"❌ 启动MCP服务器失败: {e}")
            print("💡 请确保:")
            print("   1. Node.js 已安装")
            print("   2. open-webSearch-main/build/index.js 文件存在")
            print("   3. 3002端口未被占用")
            return False

    async def initialize_mcp_session(self):
        """初始化MCP会话"""
        try:
            import aiohttp

            print("📡 发送MCP初始化请求...")

            # 发送初始化请求
            init_request = {
                "jsonrpc": "2.0",
                "id": 0,
                "method": "initialize",
                "params": {
                    "protocolVersion": "2024-11-05",
                    "capabilities": {},
                    "clientInfo": {
                        "name": "TFT-Assistant",
                        "version": "1.0.0"
                    }
                }
            }

            print(f"🌐 连接到: http://localhost:3002/mcp")

            async with aiohttp.ClientSession() as session:
                headers = {
                    'Content-Type': 'application/json',
                    'Accept': 'application/json, text/event-stream'
                }

                async with session.post(
                    'http://localhost:3002/mcp',
                    json=init_request,
                    headers=headers,
                    timeout=15
                ) as response:
                    print(f"📋 响应状态: {response.status}")
                    print(f"📋 响应头: {dict(response.headers)}")
                    if response.status == 200:
                        # 从响应头获取session ID
                        session_id = response.headers.get('mcp-session-id')
                        if session_id:
                            self.session_id = session_id
                            print(f"✅ MCP会话初始化成功, Session ID: {session_id}")

                            try:
                                # 读取SSE响应
                                response_text = await response.text()
                                print(f"🔍 MCP初始化响应: {response_text[:300]}...")
                                return True
                            except Exception as e:
                                print(f"⚠️ 读取响应失败: {e}")
                                # 即使读取失败，session已经建立，继续尝试
                                return True
                        else:
                            print("⚠️ 未找到Session ID")
                            print(f"🔍 所有响应头: {list(response.headers.keys())}")
                            return False
                    else:
                        try:
                            error_text = await response.text()
                            print(f"⚠️ MCP初始化失败: {response.status}")
                            print(f"📋 错误详情: {error_text}")
                        except:
                            print(f"⚠️ MCP初始化失败: {response.status} (无法读取错误详情)")
                        return False

        except Exception as e:
            print(f"❌ MCP会话初始化失败: {e}")
            print("💡 可能的原因:")
            print("   1. MCP服务器未启动")
            print("   2. 端口3002被占用")
            print("   3. 网络连接问题")
            return False

    async def stop_server(self):
        """停止MCP服务器"""
        if self.server_process:
            try:
                self.server_process.terminate()
                await asyncio.sleep(1)
                if self.server_process.poll() is None:
                    self.server_process.kill()
                self.is_running = False
                print("🛑 MCP搜索服务器已停止")
            except Exception as e:
                print(f"⚠️ 停止MCP服务器失败: {e}")

    async def search(self, query: str, engine: str = "bing", limit: int = 5) -> List[SearchResult]:
        """执行联网搜索"""
        if not self.is_running:
            if not await self.start_server():
                return []

        if not self.session_id:
            print("🔄 MCP会话未初始化，尝试重新初始化...")
            if not await self.initialize_mcp_session():
                print("❌ MCP会话初始化失败")
                return []

        try:
            print(f"🔍 使用 {engine} 引擎搜索: {query}")

            # 使用HTTP API进行搜索
            import aiohttp

            search_request = {
                "jsonrpc": "2.0",
                "id": self.search_id,
                "method": "tools/call",
                "params": {
                    "name": "search",
                    "arguments": {
                        "query": query,
                        "engine": engine,
                        "limit": limit
                    }
                }
            }
            self.search_id += 1

            # 发送HTTP请求，包含session ID
            headers = {
                'Content-Type': 'application/json',
                'Accept': 'application/json, text/event-stream',
                'mcp-session-id': self.session_id
            }

            async with aiohttp.ClientSession() as session:
                async with session.post(
                    'http://localhost:3002/mcp',
                    json=search_request,
                    headers=headers,
                    timeout=30
                ) as response:
                    if response.status == 200:
                        # 处理SSE格式响应
                        response_text = await response.text()
                        print(f"🔍 搜索响应 (前500字符): {response_text[:500]}...")
                        return self._parse_sse_response(response_text)
                    else:
                        error_text = await response.text()
                        print(f"⚠️ HTTP请求失败: {response.status} - {error_text}")
                        return []

        except Exception as e:
            print(f"❌ 搜索失败: {e}")
            return []

    def _parse_sse_response(self, sse_text: str) -> List[SearchResult]:
        """解析SSE格式的响应"""
        results = []

        try:
            print(f"🔍 解析SSE响应 (长度: {len(sse_text)})")

            # SSE格式: event: message\ndata: {...}\n\n
            lines = sse_text.split('\n')
            current_data = ""

            for line in lines:
                if line.startswith('data:'):
                    current_data = line[5:].strip()  # 移除'data:'前缀
                    print(f"📄 数据内容: {current_data[:200]}...")

                    try:
                        # 解析JSON数据
                        data = json.loads(current_data)

                        if "result" in data and "content" in data["result"]:
                            content = data["result"]["content"]
                            print(f"📋 找到内容: {len(content)} 个项目")

                            for item in content:
                                if "text" in item:
                                    # 解析搜索结果文本
                                    result_text = item["text"]
                                    print(f"📄 搜索结果文本: {result_text[:300]}...")

                                    # 尝试解析JSON格式的结果
                                    try:
                                        # 清理文本，移除可能的换行符和空格
                                        cleaned_text = result_text.strip()
                                        print(f"🔍 清理后的文本 (前200字符): {cleaned_text[:200]}...")

                                        # 尝试解析为完整的JSON对象
                                        if cleaned_text.startswith('{'):
                                            # 如果是JSON对象格式
                                            json_data = json.loads(cleaned_text)
                                            print(f"🔍 解析JSON对象成功")

                                            # 检查是否包含results字段
                                            if 'results' in json_data:
                                                search_results = json_data['results']
                                                print(f"🔍 找到results字段: {len(search_results)} 个结果")

                                                for search_result in search_results:
                                                    if isinstance(search_result, dict):
                                                        results.append(SearchResult(
                                                            title=search_result.get('title', '无标题'),
                                                            url=search_result.get('url', ''),
                                                            snippet=search_result.get('description', search_result.get('snippet', '无描述')),
                                                            engine=search_result.get('engine', 'MCP'),
                                                            timestamp=search_result.get('timestamp', time.strftime("%Y-%m-%d %H:%M:%S"))
                                                        ))
                                            else:
                                                print("⚠️ 未找到results字段")

                                        elif cleaned_text.startswith('['):
                                            # 如果是JSON数组格式
                                            json_results = json.loads(cleaned_text)
                                            print(f"🔍 解析JSON数组: {len(json_results)} 个结果")
                                            for json_result in json_results:
                                                if isinstance(json_result, dict):
                                                    results.append(SearchResult(
                                                        title=json_result.get('title', '无标题'),
                                                        url=json_result.get('url', ''),
                                                        snippet=json_result.get('description', json_result.get('snippet', '无描述')),
                                                        engine=json_result.get('engine', 'MCP'),
                                                        timestamp=json_result.get('timestamp', time.strftime("%Y-%m-%d %H:%M:%S"))
                                                    ))
                                        else:
                                            # 解析文本格式的结果
                                            print("📝 使用文本解析")
                                            results.extend(self._parse_text_results(result_text))
                                    except json.JSONDecodeError as e:
                                        print(f"⚠️ JSON解析失败: {e}")
                                        # 如果不是JSON，尝试文本解析
                                        print("📝 使用文本解析")
                                        results.extend(self._parse_text_results(result_text))
                                    break

                        elif "error" in data:
                            print(f"❌ MCP搜索错误: {data['error']}")

                    except json.JSONDecodeError as e:
                        print(f"⚠️ JSON解析失败: {e}")
                        # 尝试直接作为文本结果处理
                        results.extend(self._parse_text_results(current_data))

                elif line.startswith('event:'):
                    print(f"📡 事件类型: {line[6:].strip()}")

        except Exception as e:
            print(f"⚠️ 解析SSE响应失败: {e}")

        print(f"✅ SSE解析完成，找到 {len(results)} 个结果")
        return results

    def _parse_text_results(self, text: str) -> List[SearchResult]:
        """解析文本格式的搜索结果"""
        results = []
        try:
            lines = text.split('\n')
            for line in lines:
                if line.strip() and ('http' in line or 'www.' in line):
                    # 尝试提取标题、URL和描述
                    parts = line.split(' - ')
                    if len(parts) >= 2:
                        title = parts[0].strip()
                        rest = ' - '.join(parts[1:])

                        # 查找URL
                        url = ""
                        for word in rest.split():
                            if word.startswith('http') or word.startswith('www.'):
                                url = word.strip('[]()')
                                break

                        if url:
                            snippet = rest.replace(url, '').strip(' -')
                            results.append(SearchResult(
                                title=title,
                                url=url,
                                snippet=snippet,
                                engine="MCP",
                                timestamp=time.strftime("%Y-%m-%d %H:%M:%S")
                            ))
        except Exception as e:
            print(f"⚠️ 文本解析失败: {e}")

        return results

    def _parse_search_response(self, response: Dict) -> List[SearchResult]:
        """解析MCP搜索响应（JSON格式）"""
        results = []

        try:
            print(f"🔍 解析MCP响应: {response}")

            if "result" in response and "content" in response["result"]:
                content = response["result"]["content"]

                for item in content:
                    if "text" in item:
                        # 解析搜索结果文本
                        result_text = item["text"]
                        print(f"📄 搜索结果文本: {result_text[:200]}...")

                        # 尝试解析JSON格式的结果
                        try:
                            if result_text.strip().startswith('['):
                                # 如果是JSON数组格式
                                json_results = json.loads(result_text)
                                for json_result in json_results:
                                    if isinstance(json_result, dict):
                                        results.append(SearchResult(
                                            title=json_result.get('title', '无标题'),
                                            url=json_result.get('url', ''),
                                            snippet=json_result.get('snippet', '无描述'),
                                            engine=json_result.get('engine', 'MCP'),
                                            timestamp=json_result.get('timestamp', time.strftime("%Y-%m-%d %H:%M:%S"))
                                        ))
                            else:
                                # 解析文本格式的结果
                                lines = result_text.split('\n')
                                for line in lines:
                                    if line.strip() and ('http' in line or 'www.' in line):
                                        # 尝试提取标题、URL和描述
                                        parts = line.split(' - ')
                                        if len(parts) >= 2:
                                            title = parts[0].strip()
                                            rest = ' - '.join(parts[1:])

                                            # 查找URL
                                            url = ""
                                            for word in rest.split():
                                                if word.startswith('http') or word.startswith('www.'):
                                                    url = word.strip('[]()')
                                                    break

                                            if url:
                                                snippet = rest.replace(url, '').strip(' -')
                                                results.append(SearchResult(
                                                    title=title,
                                                    url=url,
                                                    snippet=snippet,
                                                    engine="MCP",
                                                    timestamp=time.strftime("%Y-%m-%d %H:%M:%S")
                                                ))
                        except json.JSONDecodeError:
                            # 如果不是JSON，尝试文本解析
                            lines = result_text.split('\n')
                            for line in lines:
                                if line.strip() and ('http' in line or 'www.' in line):
                                    parts = line.split(' - ')
                                    if len(parts) >= 2:
                                        title = parts[0].strip()
                                        rest = ' - '.join(parts[1:])
                                        url = ""
                                        for word in rest.split():
                                            if word.startswith('http') or word.startswith('www.'):
                                                url = word.strip('[]()')
                                                break
                                        if url:
                                            snippet = rest.replace(url, '').strip(' -')
                                            results.append(SearchResult(
                                                title=title,
                                                url=url,
                                                snippet=snippet,
                                                engine="MCP",
                                                timestamp=time.strftime("%Y-%m-%d %H:%M:%S")
                                            ))
                        break

            elif "error" in response:
                print(f"❌ MCP搜索错误: {response['error']}")

        except Exception as e:
            print(f"⚠️ 解析搜索结果失败: {e}")

        print(f"✅ 解析完成，找到 {len(results)} 个结果")
        return results

    async def search_tft_specific(self, query: str) -> List[SearchResult]:
        """云顶之弈专门搜索"""
        # 使用中文搜索引擎搜索TFT相关内容
        engines = ["baidu", "bing", "csdn"]
        all_results = []

        for engine in engines:
            try:
                tft_query = f"云顶之弈 {query}"
                results = await self.search(tft_query, engine, limit=3)
                all_results.extend(results)
                await asyncio.sleep(0.5)  # 避免请求过快
            except Exception as e:
                print(f"⚠️ {engine} 搜索失败: {e}")
                continue

        # 去重并返回前5个结果
        seen_urls = set()
        unique_results = []
        for result in all_results:
            if result.url not in seen_urls:
                seen_urls.add(result.url)
                unique_results.append(result)
                if len(unique_results) >= 5:
                    break

        return unique_results

# 模拟MCP搜索客户端（备用方案）
class MockMCPWebSearchClient:
    """模拟MCP搜索客户端 - 当MCP服务器不可用时使用"""

    def __init__(self):
        self.search_id = 0

    async def start_server(self):
        """模拟启动服务器"""
        print("🔄 使用模拟搜索模式")
        return True

    async def stop_server(self):
        """模拟停止服务器"""
        pass

    async def search(self, query: str, engine: str = "bing", limit: int = 5) -> List[SearchResult]:
        """模拟搜索功能"""
        print(f"🔍 模拟搜索 ({engine}): {query}")

        # 模拟搜索延迟
        await asyncio.sleep(1)

        # 根据查询内容返回模拟结果
        if "云顶之弈" in query or "TFT" in query:
            return self._get_tft_mock_results(query)
        else:
            return self._get_general_mock_results(query)

    def _get_tft_mock_results(self, query: str) -> List[SearchResult]:
        """获取云顶之弈模拟搜索结果"""
        return [
            SearchResult(
                title=f"云顶之弈 {query} 最新攻略",
                url="https://www.op.gg/tft/guide",
                snippet=f"最新的云顶之弈{query}攻略，包含阵容推荐、装备选择、运营技巧等详细内容。",
                engine="OPGG",
                timestamp=time.strftime("%Y-%m-%d %H:%M:%S")
            ),
            SearchResult(
                title=f"{query}阵容强度分析 - LolChess",
                url="https://lolchess.gg/meta",
                snippet=f"当前版本{query}的详细数据分析，胜率、登场率变化趋势，以及在不同段位的表现。",
                engine="LoLChess",
                timestamp=time.strftime("%Y-%m-%d %H:%M:%S")
            ),
            SearchResult(
                title=f"云顶之弈{query}完全指南 - Game8",
                url="https://game8.gg/tft/guide",
                snippet=f"从入门到精通的{query}完整指南，包含基础规则、进阶技巧和实战案例。",
                engine="Game8",
                timestamp=time.strftime("%Y-%m-%d %H:%M:%S")
            )
        ]

    def _get_general_mock_results(self, query: str) -> List[SearchResult]:
        """获取通用模拟搜索结果"""
        return [
            SearchResult(
                title=f"{query} - 搜索结果",
                url="https://www.example.com/search",
                snippet=f"关于{query}的相关信息和资源。",
                engine="MockSearch",
                timestamp=time.strftime("%Y-%m-%d %H:%M:%S")
            )
        ]

    async def search_tft_specific(self, query: str) -> List[SearchResult]:
        """云顶之弈专门搜索"""
        return await self.search(f"云顶之弈 {query}", "bing", 5)

# 智能搜索客户端 - 自动选择真实或模拟搜索
class SmartWebSearchClient:
    """智能搜索客户端"""

    def __init__(self):
        self.mcp_client = MCPWebSearchClient()
        self.mock_client = MockMCPWebSearchClient()
        self.use_mock = False

    async def initialize(self):
        """初始化搜索客户端"""
        try:
            # 尝试启动真实的MCP服务器
            if await self.mcp_client.start_server():
                self.use_mock = False
                print("✅ 使用真实MCP搜索")
                return True
            else:
                self.use_mock = True
                print("⚠️ MCP服务器启动失败，使用模拟搜索")
                return True
        except Exception as e:
            print(f"⚠️ 初始化搜索客户端失败，使用模拟搜索: {e}")
            self.use_mock = True
            return True

    async def search(self, query: str, engine: str = "bing", limit: int = 5) -> List[SearchResult]:
        """统一搜索接口"""
        if self.use_mock:
            return await self.mock_client.search(query, engine, limit)
        else:
            return await self.mcp_client.search(query, engine, limit)

    async def search_tft_specific(self, query: str) -> List[SearchResult]:
        """云顶之弈专门搜索"""
        if self.use_mock:
            return await self.mock_client.search_tft_specific(query)
        else:
            return await self.mcp_client.search_tft_specific(query)

    async def close(self):
        """关闭搜索客户端"""
        if not self.use_mock:
            await self.mcp_client.stop_server()

def format_search_results(results: List[SearchResult]) -> str:
    """格式化搜索结果为可读文本"""
    if not results:
        return "❌ 未找到相关搜索结果"

    formatted = f"🌐 联网搜索结果 (共 {len(results)} 条):\n\n"

    for i, result in enumerate(results, 1):
        formatted += f"{i}. **{result.title}**\n"
        formatted += f"   🔗 链接: {result.url}\n"
        formatted += f"   📝 描述: {result.snippet}\n"
        formatted += f"   🌐 搜索引擎: {result.engine}\n"
        if result.timestamp:
            formatted += f"   🕐 时间: {result.timestamp}\n"
        formatted += "\n"

    return formatted

# 测试代码
async def test_web_search():
    """测试联网搜索功能"""
    client = SmartWebSearchClient()

    try:
        await client.initialize()

        # 测试通用搜索
        print("\n" + "="*50)
        print("测试通用搜索")
        print("="*50)
        results = await client.search("Python编程教程", "bing", 3)
        print(format_search_results(results))

        # 测试TFT专门搜索
        print("\n" + "="*50)
        print("测试云顶之弈专门搜索")
        print("="*50)
        tft_results = await client.search_tft_specific("最强阵容")
        print(format_search_results(tft_results))

    finally:
        await client.close()

if __name__ == "__main__":
    asyncio.run(test_web_search())